#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "comm.h"
#include "device.h"
#include "dlist.h"

int g_dev_id_min = 10001;
int g_dev_num = 0;
node_t *g_list_head = NULL;

int generate_id()
{
	return g_dev_id_min++;
}

void showfun_dev_full(const void *data)
{
	device_t *dev = (device_t *)data;
	printf("%d\t%s\t%s\t%s\t%f\n", 
			dev->dev_id, 
			dev->dev_name, 
			dev->dev_type, 
			dev->dev_ip, 
			dev->dev_power);
}

int cmpfun_dev_id(const void *data1, const void *data2)
{
	device_t *temp1 = (device_t *)data1;
	device_t *temp2 = (device_t *)data2;

	return temp1->dev_id - temp2->dev_id;
}

int cmpfun_dev_name(const void *data1, const void *data2)
{
	device_t *temp1 = (device_t *)data1;
	device_t *temp2 = (device_t *)data2;

	return strcmp(temp1->dev_name, temp2->dev_name);
}

int cmpfun_dev_type(const void *data1, const void *data2)
{
	device_t *temp1 = (device_t *)data1;
	device_t *temp2 = (device_t *)data2;

	return strcmp(temp1->dev_type, temp2->dev_type);
}

int updatefun_dev_name(void *old_name, const void *new_name)
{
	device_t *temp1 = (device_t *)old_name;
	device_t *temp2 = (device_t *)new_name;

	strncpy(temp1->dev_name, temp2->dev_name, sizeof(temp1->dev_name) - 1);
	return 0;
}

int updatefun_dev_type(void *old_type, const void *new_type)
{
	device_t *temp1 = (device_t *)old_type;
	device_t *temp2 = (device_t *)new_type;

	strncpy(temp1->dev_type, temp2->dev_type, sizeof(temp1->dev_type) - 1);
	return 0;
}

int updatefun_dev_ip(void *old_ip, const void *new_ip)
{
	device_t *temp1 = (device_t *)old_ip;
	device_t *temp2 = (device_t *)new_ip;

	strncpy(temp1->dev_ip, temp2->dev_ip, sizeof(temp1->dev_ip) - 1);
	return 0;
}

node_t *load_dev()
{
	FILE *fp = NULL;
	device_t dev_node;
	dev_info_t dev_info;

	// 检查文件是否存在
	if(access(DEV_FILE, F_OK) != 0)
	{
		// 不存在就创建文件
		fp = fopen(DEV_FILE, "w");
		if(!fp)
		{
			perror("Fopen failed.\n");
			return NULL;
		}
		// 初始化数据
		memset(&dev_info, 0, sizeof(dev_info_t));
		// 将dev_info所指向的大小为sizeof(dev_info)且个数为1的数据写入fp
		fwrite(&dev_info, sizeof(dev_info), 1, fp);
		// 关闭文件
		fclose(fp);
		fp = NULL;
	}

	// 打开设备文件
	fp = fopen(DEV_FILE, "r");
	if(!fp)
	{
		perror("Fopen failed.\n");
		return NULL;
	}

	// 创建链表
	g_list_head = create_dlist();
	if(!g_list_head)
	{
		fclose(fp);
		return NULL;
	}

	// 初始化数据
	memset(&dev_info, 0, sizeof(dev_info_t));
	// 从fp读取大小为sizeof(dev_info_t)且数量为1的数据到dev_info
	fread(&dev_info, sizeof(dev_info_t), 1, fp);
	// 用文件头信息更新全局变量的值
	g_dev_num = dev_info.dev_num; // 文件中的设备数
	if(dev_info.max_id != 0)
		g_dev_id_min = dev_info.max_id; // 最大id值

	memset(&dev_node, 0, sizeof(device_t));
	for(int i = 0; i < dev_info.dev_num; i++)
	{
		// 读取一条设备信息
		fread(&dev_node, sizeof(device_t), 1, fp);
		// 插入链表
		insert_hdlist(g_list_head, &dev_node, sizeof(device_t));
	}

	// 关闭文件，返回链表头
	fclose(fp);
	return g_list_head;
}

int save_dev(node_t *head)
{
	node_t *temp = NULL;
	FILE *fp = NULL;
	dev_info_t dev_info;
	device_t *p_dev_node = NULL;

	// 清空链表头
	memset(&dev_info, 0, sizeof(dev_info));

	if(!head)
		return -1;

	// 打开文件
	fp = fopen(DEV_FILE, "w+b");
	if(!fp)
	{
		perror("Fopen failed\n");
		return -1;
	}

	// 用全局变量更新文件头信息，然后写入文件
	dev_info.dev_num = g_dev_num;
	dev_info.max_id = g_dev_id_min;
	fwrite(&dev_info, sizeof(dev_info_t), 1, fp);

	// 遍历链表
	temp = head->next;
	while(temp != head)
	{
		p_dev_node = (device_t *)temp->data;

		// 将链表信息写入文件
		fwrite(p_dev_node, sizeof(device_t), 1, fp);
		temp = temp->next;
	}
	// 关闭文件
	fclose(fp);
	return 0;
}

int add_dev(node_t *head, const device_t *new_dev)
{
	device_t *new_node = malloc(sizeof(device_t));
	if(!new_node)
		return -1;

	// 复制设备数据
	memcpy(new_node, new_dev, sizeof(device_t));
	// 设置唯一id
	new_node->dev_id = generate_id();

	int ret = insert_hdlist(head, (void *)new_dev, sizeof(device_t));
	if(ret == 0)
	{
		g_dev_num++;
		g_modify_flag = 1;
	}
	else
	{
		// 释放临时节点
		free(new_node);
	}

	return ret;
}

node_t *find_dev(node_t *head, cmpfun_t cmpfun, const device_t *cmpdev)
{
	node_t *new_head = create_dlist();
	if(!new_head)
		return NULL;

	node_t *temp = head->next;
	while(temp != head)
	{
		device_t *p_dev_node = (device_t *)temp->data;
		if(cmpfun(p_dev_node, cmpdev) == 0)
		{
			device_t *new_dev = malloc(sizeof(device_t));
			if(!new_dev)
			{
				destroy_dlist(&new_head);
				return NULL;
			}
			memcpy(new_dev, p_dev_node, sizeof(device_t));
			insert_tdlist(new_head, new_dev, sizeof(device_t));
		}
		temp = temp->next;
	}
	return new_head;
}

int del_dev(node_t *head, cmpfun_t cmpfun, const device_t *delete_dev)
{
#if 0
	node_t *temp = find_dlist(head, (void *)&delete_dev, (pfunc_cmp_t)cmpfun);
	if(!temp)
		return -1;

	// 删除节点并更新链表指针
	// delete_hdlist(temp); 
	node_t *new_temp = temp->next;
	temp->next = new_temp->next;
	temp->next->pre = temp;
#endif

	node_t *pre = head;
	node_t *temp = head->next;
	while(temp != head)
	{
		if(cmpfun(temp->data, delete_dev) == 0)
		{
			pre->next = temp->next;
			temp->next->pre = pre;
			free(temp->data);
			free(temp);
			// 更新全局变量
			g_dev_num--;
			g_modify_flag = 1;
			break;
		}
		pre = temp;
		temp = temp->next;
	}
	
	return 0;
}

node_t *update_dev(
		node_t *head,
		int id,
		update_fun_t update_fun,
		device_t  *update_dev)
{
	if(!head)
		return NULL;
	if(is_empty_dlist(head))
		return NULL;
	if(!update_fun)
		return NULL;

	node_t *temp = head->next;
	while(temp != head)
	{
		device_t *newnode = temp->data;
		if(newnode->dev_id == id)
		{
			update_fun(temp->data, (void *)update_dev);
		}
		temp = temp->next;
	}
}

int sort_dev(node_t *head, cmpfun_t cmpfun)
{
	if(!head)
		return -1;

	if(is_empty_dlist(head))
		return -1;
#if 0
	node_t *temp1 = NULL;
	node_t *temp2 = NULL;
	node_t *temp3 = NULL;
	void *temp = NULL;
	int flag = 0;

	for(temp = head->next, temp3 = head->pre; temp1 != head; temp1 = temp1->next, temp3 = temp3->pre)
	{
		flag = 0;
		for(temp2 = head->next; temp2 != head && temp2 != temp3; temp2 = temp2->next)
		{
			void *p_data1 = temp2->data;
			void *p_data2 = temp2->next->data;
			if((!p_data1) || (!p_data2))
				continue;
			if(cmpfun(p_data1, p_data2) > 0)
			{
				temp = temp2->data;
				temp2->data = temp2->next->data;
				temp2->next->data = temp;
				flag = 1;
			}
		}

		if(0 == flag)
			break;
	}
#endif
	node_t *temp1 = NULL; // 类似bubble_sort中的i
	node_t *temp2 = NULL; // 类似bubble_sort中的j
	void *temp = NULL;
	int flag;

	for(temp1 = head->next; temp1 != head; temp1 = temp1->next)
	{
		for(temp2 = head->next; temp2 != head; temp2 = temp2->next)
		{
			void *pstu1 = temp2->data;
			void *pstu2 = temp2->next->data;
			if((!pstu1) || (!pstu2))
			{
				continue;
			}

			if(cmpfun(pstu1, pstu2) > 0) // 比较名字
			{
				temp = temp2->data;
				temp2->data = temp2->next->data;
				temp2->next->data = temp;
				flag = 1;
			}
		}
		if(0 == flag)
			break;
	}

	return 0;
}

void show_dev(node_t *head, showfun_t showfun)
{
	if(is_empty_dlist(head))
		return ;

	show_dlist(head, (pfunc_show_t)showfun);
}
